package com.dongdongqiang.common.query;

import com.dongdongqiang.common.utils.DateUtil;
import com.dongdongqiang.common.utils.ReflectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.persistence.Column;
import javax.persistence.Transient;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 创建搜索方法的美剧
 * Created by zhangzhenbin on 2016/12/29.
 */
public class QueryMethodBuilder {
    private static final Logger logger = LoggerFactory.getLogger(QueryMethodBuilder.class);
    public static <T extends PageSearchForm> List<QueryMethodItem> build(T searchForm, Class tableClazz) throws IllegalAccessException, NoSuchFieldException {
        List<QueryMethodItem> list = new ArrayList<>();
        Class<? extends PageSearchForm> searchFormClazz = searchForm.getClass();
        Field[] searchFormFields = ReflectionUtils.getAllDeclaredFields(searchFormClazz);
        for (Field searchFormField : searchFormFields) {
            //如果是pageSize，curPageNO，pageProvider字段，则直接忽略
            if (searchFormField.getName().equals("pageSize")
                    || searchFormField.getName().equals("curPageNO")
                    || searchFormField.getName().equals("pageProvider")
                    || searchFormField.getName().equals("orderBy")) continue;
            //如果是有Transient注解，也直接忽略
            Transient aTransient = searchFormField.getAnnotation(Transient.class);
            if (aTransient != null) continue;

            String searchFormFieldName = searchFormField.getName();
            QueryMethodEnum[] enums = QueryMethodEnum.values();
            for (QueryMethodEnum anEnum : enums) {
                if (searchFormFieldName.startsWith(anEnum.name() + "_")) {
                    QueryMethodItem queryMethodItem = new QueryMethodItem();
                    queryMethodItem.setMethod(anEnum);
                    queryMethodItem.setValue(FieldUtils.readDeclaredField(searchForm,searchFormFieldName,true));
                    String fieldName = searchFormFieldName.replace(anEnum.name() + "_", "");
                    try {
                        Field declaredField = ReflectionUtils.getAllDeclaredField(tableClazz, fieldName);
                        Column columnAnnotation = declaredField.getAnnotation(Column.class);
                        String columnName = columnAnnotation.name();
                        queryMethodItem.setColumnName(columnName);
                        queryMethodItem.setType(declaredField.getType());

                    } catch (Exception e) {
                        logger.error("没有在["+tableClazz.getName()+"]中找到["+fieldName+"]字段");
                        continue;
                    }

                    list.add(queryMethodItem);
                }
            }

        }
        return list;
    }

    /**
     * 将 methodItemList转换为SQL 和 参数
     * @param methodItemList
     * @param sqlCondition
     * @param params
     */
    public static void methodItemListBuilder(List<QueryMethodItem> methodItemList, StringBuilder sqlCondition, List<Object> params){
        for (QueryMethodItem item : methodItemList) {
            //包含空值就取消
            if (item.getMethod() == null ||
                    StringUtils.isBlank(item.getColumnName()) ||
                    item.getType() == null ||
                    item.getValue() == null ||
                    (item.getValue() instanceof String && StringUtils.isBlank((String) item.getValue()))
                    ) continue;

            sqlCondition
                    .append("and ")
                    .append("t.")
                    .append(item.getColumnName())
                    .append(" ")
                    .append(item.getMethod().getValue())
                    .append(" ? ");
            Object value = item.getValue();
            if (item.getMethod().equals(QueryMethodEnum.contain)) {
                value = "%" + value + "%";
            }
            if (item.getType().equals(Date.class) && value instanceof String) {
                value = DateUtil.stringForceToDate((String) value);
            }
            params.add(value);
        }
    }
}
